package com.woniuxy.flowable.service.impl;

import com.woniuxy.flowable.service.CustomerFlowableService;
import lombok.extern.slf4j.Slf4j;
import org.flowable.engine.*;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.task.api.Task;
import org.flowable.task.api.history.HistoricTaskInstance;
import org.flowable.task.api.history.HistoricTaskInstanceQuery;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * 客户审批流程服务实现类
 * @author woniuxy
 */
@Slf4j
@Service
public class CustomerFlowableServiceImpl implements CustomerFlowableService {

    @Autowired
    private RuntimeService runtimeService;
    
    @Autowired
    private TaskService taskService;
    
    @Autowired
    private RepositoryService repositoryService;
    
    @Autowired
    private HistoryService historyService;
    
    @Autowired
    private IdentityService identityService;

    @Override
    public String startCustomerProcess(String processDefinitionKey, String businessKey, Map<String, Object> variables) {
        try {
            // 启动流程实例
            ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(processDefinitionKey, businessKey, variables);
            log.info("客户审批流程启动成功，流程实例ID: {}, 业务Key: {}", processInstance.getId(), businessKey);
            return processInstance.getId();
        } catch (Exception e) {
            log.error("启动客户审批流程失败", e);
            throw new RuntimeException("启动客户审批流程失败: " + e.getMessage(), e);
        }
    }

    @Override
    public List<Map<String, Object>> getPendingTasks(String userName) {
        try {
            List<Task> tasks = taskService.createTaskQuery()
                    .taskAssignee(userName)
                    .active()
                    .list();
            
            // 查询候选任务
            List<Task> candidateTasks = taskService.createTaskQuery()
                    .taskCandidateUser(userName)
                    .active()
                    .list();
            
            // 合并任务列表
            Set<Task> allTasks = new HashSet<>(tasks);
            allTasks.addAll(candidateTasks);
            
            List<Map<String, Object>> result = new ArrayList<>();
            for (Task task : allTasks) {
                Map<String, Object> taskInfo = new HashMap<>();
                taskInfo.put("taskId", task.getId());
                taskInfo.put("taskName", task.getName());
                taskInfo.put("processInstanceId", task.getProcessInstanceId());
                taskInfo.put("processDefinitionId", task.getProcessDefinitionId());
                taskInfo.put("assignee", task.getAssignee());
                taskInfo.put("createTime", task.getCreateTime());
                taskInfo.put("dueDate", task.getDueDate());
                
                // 获取流程变量
                Map<String, Object> variables = taskService.getVariables(task.getId());
                taskInfo.put("variables", variables);
                
                result.add(taskInfo);
            }
            
            log.info("查询客户审批待办任务成功，用户: {}, 任务数量: {}", userName, result.size());
            return result;
            
        } catch (Exception e) {
            log.error("查询客户审批待办任务失败", e);
            throw new RuntimeException("查询待办任务失败: " + e.getMessage(), e);
        }
    }

    @Override
    public List<Map<String, Object>> getCompletedTasks(String userName) {
        try {
            // 查询直接分配给用户的历史任务
            HistoricTaskInstanceQuery assigneeQuery = historyService.createHistoricTaskInstanceQuery()
                    .taskAssignee(userName)
                    .finished()
                    .orderByHistoricTaskInstanceEndTime()
                    .desc();
            
            List<HistoricTaskInstance> assigneeTasks = assigneeQuery.list();
            
            // 查询用户作为候选人的历史任务
            HistoricTaskInstanceQuery candidateQuery = historyService.createHistoricTaskInstanceQuery()
                    .taskCandidateUser(userName)
                    .finished()
                    .orderByHistoricTaskInstanceEndTime()
                    .desc();
            
            List<HistoricTaskInstance> candidateTasks = candidateQuery.list();
            
            // 合并任务列表，使用Set去重
            Set<HistoricTaskInstance> allTasks = new HashSet<>(assigneeTasks);
            allTasks.addAll(candidateTasks);
            
            // 按结束时间排序
            List<HistoricTaskInstance> sortedTasks = allTasks.stream()
                    .sorted((t1, t2) -> {
                        if (t1.getEndTime() == null && t2.getEndTime() == null) return 0;
                        if (t1.getEndTime() == null) return 1;
                        if (t2.getEndTime() == null) return -1;
                        return t2.getEndTime().compareTo(t1.getEndTime()); // 降序
                    })
                    .collect(ArrayList::new, ArrayList::add, ArrayList::addAll);
            
            List<Map<String, Object>> result = new ArrayList<>();
            for (HistoricTaskInstance task : sortedTasks) {
                Map<String, Object> taskInfo = new HashMap<>();
                taskInfo.put("taskId", task.getId());
                taskInfo.put("taskName", task.getName());
                taskInfo.put("processInstanceId", task.getProcessInstanceId());
                taskInfo.put("processDefinitionId", task.getProcessDefinitionId());
                taskInfo.put("assignee", task.getAssignee());
                taskInfo.put("startTime", task.getStartTime());
                taskInfo.put("endTime", task.getEndTime());
                taskInfo.put("duration", task.getDurationInMillis());
                
                // 添加任务类型标识
                boolean isAssignee = assigneeTasks.contains(task);
                taskInfo.put("taskType", isAssignee ? "ASSIGNEE" : "CANDIDATE");
                
                result.add(taskInfo);
            }
            
            log.info("查询客户审批已办任务成功，用户: {}, 任务数量: {} (直接分配: {}, 候选人: {})", 
                    userName, result.size(), assigneeTasks.size(), candidateTasks.size());
            return result;
            
        } catch (Exception e) {
            log.error("查询客户审批已办任务失败", e);
            throw new RuntimeException("查询已办任务失败: " + e.getMessage(), e);
        }
    }

    @Override
    public void completeTask(String taskId, Map<String, Object> variables) {
        try {
            if (variables != null && !variables.isEmpty()) {
                taskService.complete(taskId, variables);
            } else {
                taskService.complete(taskId);
            }
            log.info("完成客户审批任务成功，任务ID: {}", taskId);
        } catch (Exception e) {
            log.error("完成客户审批任务失败", e);
            throw new RuntimeException("完成任务失败: " + e.getMessage(), e);
        }
    }

    @Override
    public void approveTask(String processInstanceId) {
        try {
            log.info("开始处理客户审批通过，流程实例ID: {}", processInstanceId);
            
            // 检查流程实例是否存在
            ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
                    .processInstanceId(processInstanceId)
                    .singleResult();
            
            if (processInstance == null) {
                log.error("流程实例不存在，流程实例ID: {}", processInstanceId);
                throw new RuntimeException("流程实例不存在: " + processInstanceId);
            }
            
            // 查询当前活跃任务
            Task task = taskService.createTaskQuery()
                    .processInstanceId(processInstanceId)
                    .active()
                    .singleResult();
            
            if (task == null) {
                log.error("未找到活跃任务，流程实例ID: {}", processInstanceId);
                throw new RuntimeException("未找到活跃任务: " + processInstanceId);
            }
            
            String taskId = task.getId();
            log.info("找到活跃任务，任务ID: {}, 任务名称: {}, 指派人: {}", 
                    taskId, task.getName(), task.getAssignee());
            
            // 设置审批变量
            Map<String, Object> variables = new HashMap<>();
            variables.put("approved", true);
            
            // 设置任务变量
            taskService.setVariables(taskId, variables);
            log.info("已设置任务变量，任务ID: {}", taskId);
            
            // 完成任务
            taskService.complete(taskId);
            log.info("客户审批通过成功，任务ID: {}", taskId);
            
        } catch (Exception e) {
            log.error("客户审批通过失败，流程实例ID: {}", processInstanceId, e);
            throw new RuntimeException("审批通过失败: " + e.getMessage(), e);
        }
    }

    @Override
    public void rejectTask(String processInstanceId, String reason) {
        try {
            log.info("开始处理客户审批拒绝，流程实例ID: {}, 拒绝原因: {}", processInstanceId, reason);
            
            // 检查流程实例是否存在
            ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
                    .processInstanceId(processInstanceId)
                    .singleResult();
            
            if (processInstance == null) {
                log.error("流程实例不存在，流程实例ID: {}", processInstanceId);
                throw new RuntimeException("流程实例不存在: " + processInstanceId);
            }
            
            // 查询当前活跃任务
            Task task = taskService.createTaskQuery()
                    .processInstanceId(processInstanceId)
                    .active()
                    .singleResult();
            
            if (task == null) {
                log.error("未找到活跃任务，流程实例ID: {}", processInstanceId);
                throw new RuntimeException("未找到活跃任务: " + processInstanceId);
            }
            
            String taskId = task.getId();
            log.info("找到活跃任务，任务ID: {}, 任务名称: {}, 指派人: {}", 
                    taskId, task.getName(), task.getAssignee());
            
            // 设置审批变量
            Map<String, Object> variables = new HashMap<>();
            variables.put("approved", false);
            variables.put("rejectReason", reason);
            
            // 完成任务
            taskService.complete(taskId, variables);
            log.info("客户审批拒绝成功，任务ID: {}, 拒绝原因: {}", taskId, reason);
            
        } catch (Exception e) {
            log.error("客户审批拒绝失败，流程实例ID: {}", processInstanceId, e);
            throw new RuntimeException("审批拒绝失败: " + e.getMessage(), e);
        }
    }


    @Override
    public Map<String, Object> getProcessStatus(String processInstanceId) {
        try {
            ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
                    .processInstanceId(processInstanceId)
                    .singleResult();
            
            Map<String, Object> status = new HashMap<>();
            
            if (processInstance != null) {
                status.put("processInstanceId", processInstance.getId());
                status.put("processDefinitionId", processInstance.getProcessDefinitionId());
                status.put("businessKey", processInstance.getBusinessKey());
                status.put("isActive", true);
                status.put("isEnded", false);
                
                // 获取当前任务
                List<Task> activeTasks = taskService.createTaskQuery()
                        .processInstanceId(processInstanceId)
                        .active()
                        .list();
                
                if (!activeTasks.isEmpty()) {
                    Task currentTask = activeTasks.get(0);
                    status.put("currentTaskId", currentTask.getId());
                    status.put("currentTaskName", currentTask.getName());
                    status.put("currentAssignee", currentTask.getAssignee());
                }
                
            } else {
                // 流程已结束
                status.put("processInstanceId", processInstanceId);
                status.put("isActive", false);
                status.put("isEnded", true);
            }
            
            log.info("查询客户审批流程状态成功，流程实例ID: {}", processInstanceId);
            return status;
            
        } catch (Exception e) {
            log.error("查询客户审批流程状态失败", e);
            throw new RuntimeException("查询流程状态失败: " + e.getMessage(), e);
        }
    }

    @Override
    public List<Map<String, Object>> getProcessSteps(String processInstanceId) {
        try {
            List<HistoricTaskInstance> tasks = historyService.createHistoricTaskInstanceQuery()
                    .processInstanceId(processInstanceId)
                    .orderByHistoricTaskInstanceStartTime()
                    .asc()
                    .list();
            
            List<Map<String, Object>> steps = new ArrayList<>();
            for (HistoricTaskInstance task : tasks) {
                Map<String, Object> step = new HashMap<>();
                step.put("taskId", task.getId());
                step.put("taskName", task.getName());
                step.put("assignee", task.getAssignee());
                step.put("startTime", task.getStartTime());
                step.put("endTime", task.getEndTime());
                step.put("status", task.getEndTime() != null ? "COMPLETED" : "PENDING");
                step.put("duration", task.getDurationInMillis());
                
                // 获取任务变量
                Map<String, Object> variables = taskService.getVariables(task.getId());
                step.put("variables", variables);
                
                steps.add(step);
            }
            
            log.info("查询客户审批流程步骤成功，流程实例ID: {}, 步骤数量: {}", processInstanceId, steps.size());
            return steps;
            
        } catch (Exception e) {
            log.error("查询客户审批流程步骤失败", e);
            throw new RuntimeException("查询流程步骤失败: " + e.getMessage(), e);
        }
    }
}
